import { Context, Next } from 'koa';

/**
 * 日志级别
 */
export enum LogLevel {
  ERROR = 'error',
  WARN = 'warn',
  INFO = 'info',
  DEBUG = 'debug'
}

/**
 * 日志配置接口
 */
export interface LoggerOptions {
  level?: LogLevel;
  format?: 'simple' | 'detailed' | 'json';
  includeHeaders?: boolean;
  includeBody?: boolean;
  excludePaths?: string[];
  colorize?: boolean;
}

/**
 * 默认配置
 */
const defaultOptions: LoggerOptions = {
  level: LogLevel.INFO,
  format: 'simple',
  includeHeaders: false,
  includeBody: false,
  excludePaths: ['/health', '/favicon.ico'],
  colorize: true
};

/**
 * 颜色代码
 */
const colors = {
  reset: '\x1b[0m',
  bright: '\x1b[1m',
  red: '\x1b[31m',
  green: '\x1b[32m',
  yellow: '\x1b[33m',
  blue: '\x1b[34m',
  magenta: '\x1b[35m',
  cyan: '\x1b[36m',
  white: '\x1b[37m'
};

/**
 * 根据状态码获取颜色
 */
const getStatusColor = (status: number): string => {
  if (status >= 500) return colors.red;
  if (status >= 400) return colors.yellow;
  if (status >= 300) return colors.cyan;
  if (status >= 200) return colors.green;
  return colors.white;
};

/**
 * 根据HTTP方法获取颜色
 */
const getMethodColor = (method: string): string => {
  switch (method) {
    case 'GET': return colors.green;
    case 'POST': return colors.yellow;
    case 'PUT': return colors.blue;
    case 'DELETE': return colors.red;
    case 'PATCH': return colors.magenta;
    case 'OPTIONS': return colors.cyan;
    default: return colors.white;
  }
};

/**
 * 格式化日志
 */
const formatLog = (
  ctx: Context,
  responseTime: number,
  options: LoggerOptions
): string => {
  const { method, url, status } = ctx;
  const timestamp = new Date().toISOString();
  
  switch (options.format) {
    case 'json':
      const logData: any = {
        timestamp,
        method,
        url,
        status,
        responseTime: `${responseTime}ms`,
        userAgent: ctx.get('User-Agent'),
        ip: ctx.ip
      };
      
      if (options.includeHeaders) {
        logData.headers = ctx.headers;
      }
      
      if (options.includeBody && ctx.request.body) {
        logData.requestBody = ctx.request.body;
      }
      
      return JSON.stringify(logData);
    
    case 'detailed':
      let detailedLog = `[${timestamp}] ${method} ${url} - ${status} - ${responseTime}ms`;
      detailedLog += `\n  IP: ${ctx.ip}`;
      detailedLog += `\n  User-Agent: ${ctx.get('User-Agent')}`;
      
      if (options.includeHeaders) {
        detailedLog += `\n  Headers: ${JSON.stringify(ctx.headers, null, 2)}`;
      }
      
      if (options.includeBody && ctx.request.body) {
        detailedLog += `\n  Body: ${JSON.stringify(ctx.request.body, null, 2)}`;
      }
      
      return detailedLog;
    
    case 'simple':
    default:
      if (options.colorize) {
        const methodColor = getMethodColor(method);
        const statusColor = getStatusColor(status);
        return `${methodColor}${method}${colors.reset} ${url} - ${statusColor}${status}${colors.reset} - ${colors.bright}${responseTime}ms${colors.reset}`;
      }
      return `${method} ${url} - ${status} - ${responseTime}ms`;
  }
};

/**
 * 请求日志中间件
 */
export const logger = (options: LoggerOptions = {}) => {
  const opts = { ...defaultOptions, ...options };
  
  return async (ctx: Context, next: Next) => {
    // 检查是否需要排除此路径
    if (opts.excludePaths?.some(path => ctx.path === path)) {
      await next();
      return;
    }
    
    const start = Date.now();
    
    try {
      await next();
    } catch (error) {
      // 即使出错也要记录日志
      const responseTime = Date.now() - start;
      const logMessage = formatLog(ctx, responseTime, opts);
      console.error(`${logMessage} - ERROR: ${error}`);
      throw error;
    }
    
    const responseTime = Date.now() - start;
    const logMessage = formatLog(ctx, responseTime, opts);
    
    // 根据状态码选择日志级别
    if (ctx.status >= 500) {
      console.error(logMessage);
    } else if (ctx.status >= 400) {
      console.warn(logMessage);
    } else {
      console.log(logMessage);
    }
  };
};

/**
 * 创建开发环境日志配置
 */
export const createDevLogger = () => {
  return logger({
    level: LogLevel.DEBUG,
    format: 'simple',
    includeHeaders: false,
    includeBody: false,
    colorize: true,
    excludePaths: ['/health']
  });
};

/**
 * 创建生产环境日志配置
 */
export const createProdLogger = () => {
  return logger({
    level: LogLevel.INFO,
    format: 'json',
    includeHeaders: false,
    includeBody: false,
    colorize: false,
    excludePaths: ['/health', '/favicon.ico']
  });
};

/**
 * 创建详细日志配置（用于调试）
 */
export const createDetailedLogger = () => {
  return logger({
    level: LogLevel.DEBUG,
    format: 'detailed',
    includeHeaders: true,
    includeBody: true,
    colorize: true,
    excludePaths: []
  });
};